package main

import (
	"cxchain-2023131080/common"
	"cxchain-2023131080/crypto"
	"cxchain-2023131080/kvstore/leveldb"
	"cxchain-2023131080/maker"
	"cxchain-2023131080/statedb"
	"cxchain-2023131080/statemachine"
	"cxchain-2023131080/txpool"
	"fmt"
	"os"
	"time"
)

func main() {
	dbPath := "./testdb"
	_ = os.RemoveAll(dbPath)

	db, err := leveldb.Open(dbPath)
	if err != nil {
		panic(err)
	}
	defer db.Close()

	state := statedb.NewMPTStateDB(db)
	//单个交易执行逻辑
	//// 生成密钥对
	//privKey, _ := crypto.GenerateKey()
	//pubBytes := elliptic.Marshal(privKey.PublicKey.Curve, privKey.PublicKey.X, privKey.PublicKey.Y)
	//fromAddr := common.PubKeyToAddress(pubBytes)
	//
	//// 这里给收款地址随便用一个固定的地址（确保格式正确，长度20字节）
	//toAddr, err := common.AddressFromHex("0xdef2def2def2def2def2def2def2def2def2def2")
	//if err != nil {
	//	panic(err)
	//}
	//
	//// 初始化账户（给from账户足够余额）
	//fromAcc := &common.Account{Address: fromAddr, Amount: 1000000, Nonce: 0}
	//toAcc := &common.Account{Address: toAddr, Amount: 0, Nonce: 0}
	//
	//state.UpdateAccount(fromAcc)
	//state.UpdateAccount(toAcc)
	//
	//// 构造交易
	//tx := common.Transaction{
	//	TxData: common.TxData{
	//		To:       toAddr,
	//		Nonce:    0,
	//		Value:    100000,
	//		Gas:      21000,
	//		GasPrice: 1,
	//	},
	//}
	//
	//// 签名交易
	//err = common.SignTransaction(&tx, privKey)
	//if err != nil {
	//	panic(err)
	//}
	//
	//// 执行交易
	//machine := statemachine.StateMachine{}
	//receipt := machine.Execute1(state, tx)
	//
	//fmt.Println("=== Transaction Receipt ===")
	//fmt.Printf("TxHash:  %x\n", receipt.TxHash)
	//fmt.Printf("Status:  %d\n", receipt.Status)
	//fmt.Printf("GasUsed: %d\n", receipt.GasUsed)
	//
	//fmt.Println("=== Final Account States ===")
	//fmt.Printf("From: %+v\n", state.GetAccount(fromAddr))
	//fmt.Printf("To:   %+v\n", state.GetAccount(toAddr))
	//fmt.Printf("State Root: %x\n", state.Commit())

	//调用交易池执行多笔交易
	//// 生成两个账户的密钥和地址
	//priv1, _ := crypto.GenerateKey()
	//fromAddr1 := common.PubKeyToAddress(crypto.FromECDSAPub(&priv1.PublicKey))
	//
	//priv2, _ := crypto.GenerateKey()
	//toAddr1 := common.PubKeyToAddress(crypto.FromECDSAPub(&priv2.PublicKey))
	//
	//// 初始化账户状态
	//state.UpdateAccount(&common.Account{
	//	Address: fromAddr1,
	//	Amount:  1000000,
	//	Nonce:   0,
	//})
	//state.UpdateAccount(&common.Account{
	//	Address: toAddr1,
	//	Amount:  0,
	//	Nonce:   0,
	//})
	//
	//// 初始化交易池
	//pool := txpool.NewDefualtPool(state)
	//
	//// 构造交易
	//tx1 := &common.Transaction{
	//	TxData: common.TxData{
	//		To:       toAddr1,
	//		Nonce:    1,
	//		Value:    50000,
	//		Gas:      21000,
	//		GasPrice: 1,
	//		Input:    nil,
	//	},
	//}
	//
	//// 签名交易
	//if err := common.SignTransaction(tx1, priv1); err != nil {
	//	panic(err)
	//}
	//
	//// 添加交易进交易池
	//pool.NewTx(tx1)
	//
	//// 执行交易池中的交易
	//sm := statemachine.StateMachine{}
	//sm.ExecuteFromPool(state, pool)
	//
	//// 打印结果
	//fmt.Println("=== Final Account States ===")
	//fromAcc1 := state.GetAccount(fromAddr1)
	//toAcc1 := state.GetAccount(toAddr1)
	//fmt.Printf("From: %v\n", fromAcc1)
	//fmt.Printf("To:   %v\n", toAcc1)
	//
	//fmt.Println("=== Transaction Receipt ===")
	//fmt.Printf("TxHash:  %x\n", tx1.Hash())
	//fmt.Printf("Status:  1\n")
	//fmt.Printf("GasUsed: 21000\n")

	// 生成私钥、地址
	priv1, _ := crypto.GenerateKey()
	from := common.PubKeyToAddress(crypto.FromECDSAPub(&priv1.PublicKey))

	priv2, _ := crypto.GenerateKey()
	to := common.PubKeyToAddress(crypto.FromECDSAPub(&priv2.PublicKey))

	// 设置初始账户
	state.UpdateAccount(&common.Account{Address: from, Amount: 1000000, Nonce: 0})
	state.UpdateAccount(&common.Account{Address: to, Amount: 0, Nonce: 0})

	// 创建一笔交易：from -> to，转账50000，nonce=1
	tx := &common.Transaction{
		TxData: common.TxData{
			To:       to,
			Nonce:    1,
			Value:    50000,
			Gas:      21000,
			GasPrice: 1,
		},
	}

	// 签名交易
	err = common.SignTransaction(tx, priv1)
	if err != nil {
		panic(err)
	}

	// 创建交易池，加入交易
	pool := txpool.NewDefualtPool(state)
	pool.NewTx(tx)

	// 创建状态机
	machine := statemachine.NewStateMachine()

	// 创建区块生成器
	blockMaker := maker.NewBlockMaker(pool, state, machine)
	blockMaker.Config(maker.ChainConfig{
		Duration: 2 * time.Second,
		Coinbase: from,
	})

	// 新建区块，打包交易
	blockMaker.NewBlock()
	blockMaker.Pack()
	header, body := blockMaker.Finalize()

	// 打印结果
	fmt.Println("=== 区块信息 ===")
	fmt.Printf("区块高度: %d\n", header.Height)
	fmt.Printf("交易数量: %d\n", len(body.Transactions))

	fmt.Println("=== 交易列表 ===")
	for i, tx := range body.Transactions {
		fmt.Printf("Tx #%d: %x\n", i+1, tx.Hash())
	}

	fmt.Println("=== 收据列表 ===")
	for _, receipt := range body.Receiptions {
		fmt.Printf("TxHash: %x | 状态: %d | GasUsed: %d\n", receipt.TxHash, receipt.Status, receipt.GasUsed)
	}

	// 打印账户最终状态
	fromAcc := state.GetAccount(from)
	toAcc := state.GetAccount(to)
	fmt.Println("=== 账户状态 ===")
	fmt.Printf("From: %+v\n", fromAcc)
	fmt.Printf("To:   %+v\n", toAcc)

}
